﻿using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

namespace Nemerle2.Compiler
{
  /// <summary>
  /// Description of ITypeInfo.
  /// </summary>
  public interface ITypeInfo : IMemberInfo, IComparable[ITypeInfo]
  {
    Extends                : FixedType.Class      { get; }
    Implements             : Seq[FixedType.Class] { get; }
    SelfType               : FixedType.Class      { get; }
    TypeParams             : Seq[ITypeParameterInfo]   { get; }
    
    //Namespace возвращает [] в случае если пространство имен не задано или тип вложенный.
    //"ns1.ns2" отображается в "ns1 :: "ns2" :: []
    Namespace              : list[string]         { get; }

    Accessibility          : Accessibility        { get; }
    AttributeTargets       : AttributeTargets     { get; }
    DefaultIndexerName     : string               { get; }
    FrameworkTypeName      : string               { get; }
    FullName               : string               { get; }

    IsDelegate             : bool                 { get; }
    IsEnum                 : bool                 { get; }
    IsFloating             : bool                 { get; }
    IsInterface            : bool                 { get; }
    IsModule               : bool                 { get; }
    IsNumeric              : bool                 { get; }
    IsPrimitive            : bool                 { get; }
    IsSealed               : bool                 { get; }
    IsValueType            : bool                 { get; }
    IsUnsigned             : bool                 { get; }
    IsVariantOption        : bool                 { get; }
    IsVariant              : bool                 { get; }
    LookupMemberAvailable  : bool                 { get; }
    /// Underlying type of enum. This property appcable only to enum's TypeInfo.
    UnderlyingType         : ValueOption[ITypeInfo] { get; }

    GetConstructors(bindingFlags : NBindingFlags) : Seq[IMethodInfo];

    GetDirectSuperTypes() : Seq[FixedType.Class];
    //public abstract GetExtensionPattern(name : string) : option[ExtensionPattern];

    GetFields(bindingFlags : NBindingFlags) : Seq[IFieldInfo];
    FindMethod(methodName : string, bindingFlags : NBindingFlags) : list[IMethodInfo];

    GetMembers() : Seq[IMemberInfo];
    GetMembers(bindingFlags : NBindingFlags) : Seq[IMemberInfo];

    GetNestedTypes() : Seq[ITypeInfo];
    
    GetSuperTypes() : Seq[FixedType.Class]; // все базовые классы (рекурсивно)
    HasSuperType(typeInfo : ITypeInfo) : bool;
    IsDerivedFrom(fixedType : FixedType.Class) : bool;
    IsDerivedFrom(typeInfo : ITypeInfo) : bool;
    LookupMember(name : string, forCompletion : bool = false) : Seq[IMemberInfo];
    ConstructSubst(tc : ITypeInfo, typeParams : Seq[ITypeParameterInfo], args : Seq[NType], checkParams : bool) : Subst;
    FreshSubst() : Subst;
    MakeSubst(parms : Seq[NType]) : Subst;
    MakeUncheckedSubst(parms : Seq[NType]) : Subst;
    NestingSubst(parent : ITypeInfo) : Subst;
    
    // Проверяет доступен ли данный тип извне
    // если isFriend = true то, возвращает true также для всех internal сборок
    //_Eter_ TODO: подумать над названием параметра
    IsExternallyAccessible( isFriend : bool) : bool;
  }
}
